
require 'fileutils'
require 'tokyocabinet'

module Mil
  module Object
    # This class provides a storage interface. In this particular
    # case it provides a storage interface to the Tokyo Cabinet
    # Datbase. Tokyo Cabinet provides a key/value based interface
    # similar to that expected when using a Distrubted Hash Table
    # (DHT).
    class TokyoCabinetIO
      def initialize(path)
	@path = path
	FileUtils.mkdir_p(path)

	@hdb = TokyoCabinet::HDB::new
	@hdb.tune(-1,-1,-1, TokyoCabinet::HDB::TLARGE)

	unless File.exists? "#{@path}/store.hdb"
	  open_write
	  close
	end
      end

      # Is there anything stored in the database for key: addr.
      # Returns true or false.
      def exist?(addr)
	open_read
	truth = @hdb.vsiz(addr) == -1 ? false : true
	close

	truth
      end

      # Write a KeyValue object to the database store.
      def write(keypair)
	raise ArgumentError unless keypair.is_a? Mil::Object::KeyValue

	open_write
	@hdb.put(keypair.key, keypair.value)
	close
      end

      # Read back the value stored under the key: addr.
      def read(addr)
	open_read
	value = @hdb.get(addr)
	close

	value
      end

      # Delete an entry with key (addr) from the store.
      def delete(addr)
	open_write
	value = @hdb.out(addr)
	close

	value
      end

      private
      def open_write
	if(!@hdb.open("#{@path}/store.hdb", TokyoCabinet::HDB::OWRITER | 
		      TokyoCabinet::HDB::OCREAT | TokyoCabinet::HDB::OLCKNB))
	  raise StandardError, @hdb.errmsg(@hdb.ecode)
	end
      end

      def open_read
	if(!@hdb.open("#{@path}/store.hdb"))
	  raise StandardError, @hdb.errmsg(@hdb.ecode)
	end
      end

      def close
	@hdb.close
      end
    end
  end
end
